package com.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.demo.core.exception.ParameterException;
import com.demo.dao.UserDao;
import com.demo.domain.User;
import com.demo.domain.UserDTO;
import com.demo.domain.ro.ModifyUserInfoRequest;
import com.demo.service.MailService;
import com.demo.service.UserService;
import com.demo.utils.MD5Utils;
import com.demo.utils.StringUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {

    @Autowired
    UserDao userDao;

    @Autowired
    private MailService mailService;


    @Autowired
    private StringUtils stringUtils;





    //登录
    @Override
    public User loginService(Long userid, String password) throws Exception {
        if (userid == 0l || userid == null || password.isEmpty() || password == null) {
            throw new ParameterException("userid或password为空");
        }
        User user = userDao.findByUidAndPassword(userid);
        String enPasseord = MD5Utils.inputPassToFormPass(password);
        if(!enPasseord.equals(user.getUPwd())){
            return null;
        }
        System.out.println("usersafas:" + user);
        if (user == null) {
            return null;
        }
        if (user.getUAlive() == 0) {
            throw new NullPointerException(
                    "账号：" + userid + "已注销");
        }
        //检测用户信息是否完善
        Boolean isPerfect = this.isPerfectInfo(user);
        //使用user的nickname来保存信息完善的数据（非null则表示信息已完善）
        user.setUNickname(isPerfect ? user.getUNickname() : null);
        return user;
    }

    /**
     * 修改个人信息并登录
     *
     * @param user
     * @return
     * @throws Exception
     */
    @Override
    public String loginWithPerfectInfo(User user) throws Exception {
        if (user == null || user.getUId() < 0l) {
            throw new ParameterException("user为null或uid非法");
        }
        if (!(user.getUPhone() == null) && !user.getUPhone().matches("\\d+")) {
            return "手机号需全为数字";
        }
        if (!(user.getUPhone() == null) && user.getUPhone().length() != 11) {
            return "手机号需为11位";
        }
        String email = user.getUMail();
        if (email != null && (!email.contains("@") || !email.contains("."))) {
            return "邮箱格式错误";
        }
        if (getUserById(user.getUId()) == null) {
            return "无当前用户";
        }
        Boolean isPerfect = isPerfectInfo(user);
        if (isPerfect != true) {
            return "必要信息未填写完整";
        }
        //确认账号状态
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUId, user.getUId()).eq(User::getUAlive, 1);
        User user0 = userDao.selectOne(wrapper);
        if (user0 != null) {
            //进行数量查找确认当前昵称、手机、邮箱是否已存在
            //当前用户的某字段为空时，检测其将输入的值是否已存在
            long count1 = 0l;
            long count2 = 0l;
            long count3 = 0l;
            //当字段不为空时set null
            if (stringUtils.isEmpty(user0.getUNickname())) {
                wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(User::getUNickname, user.getUNickname());
                count1 = userDao.selectCount(wrapper);
            } else {
                user.setUNickname(null);
            }
            if (stringUtils.isEmpty(user0.getUPhone())) {
                wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(User::getUPhone, user.getUPhone());
                count2 = userDao.selectCount(wrapper);
            } else {
                user.setUPhone(null);
            }
            if (stringUtils.isEmpty(user0.getUMail())) {
                wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(User::getUMail, user.getUMail());
                count3 = userDao.selectCount(wrapper);
            } else {
                user.setUMail(null);
            }
            System.out.println(count1 + " " + count2 + " " + count3);
            //count=0则表示当前值在数据库中无重复
            if (count1 > 0l || count2 > 0l || count3 > 0l) {
                return "当前昵称或手机号或邮箱已存在，请更换重试";
            }
            //真实姓名置空，不予修改
            user.setURealname(null);
            //邮箱去点前后空格
            user.setUMail(email != null ? email.trim() : null);
            int update = userDao.updateById(user);
            return update > 0 ? "1" : "修改失败";
        }
        return "当前账号已注销";
    }

    //通过用户id查找用户信息
    @Override
    public User getUserById(Long userId) throws ParameterException {
        if (userId == 0l || userId == null) {
            throw new ParameterException("userId为空");
        }
//        if (String.valueOf(userId).length() != 12) {
//            throw new ParameterException("userId值非法");
//        }
        return userDao.findUserInfoByUserid(userId);
    }

    //用户更改个人信息
    @Override
    public ModifyUserInfoRequest changeInfoService(Long uid, String unickname, String urealname, String ugender,
                                                   String uphone, String umail, String uintro, String uability) throws ParameterException {
        if (uid == null || uid == 0l || unickname.isEmpty() || urealname.isEmpty() || ugender.isEmpty() ||
                uphone.isEmpty() || umail.isEmpty() || uintro.isEmpty() || uability.isEmpty()) {
            throw new ParameterException("传入的参数有空值");
        }
        if (!ugender.equals("男") && !ugender.equals("女")) {
            throw new ParameterException("ugender值不在（男，女）的范围");
        }
        if (String.valueOf(uid).length() != 12) {
            throw new ParameterException("uid值非法");
        }
        if (!umail.contains("@")) {
            throw new ParameterException("uemail值非法");
        }
        if (!umail.equals(userDao.getEmail(uid))) {
            if (userDao.countEmail(umail) != 0) {
                throw new ParameterException("该邮箱已存在");
            }
        }
        if (!unickname.equals(userDao.getNickname(uid))) {
            if (userDao.countNickname(unickname) != 0) {
                throw new ParameterException("该昵称已存在");
            }
        }
        ModifyUserInfoRequest result = userDao.findByUserid(uid);
        //用户存在且账号仍活跃时修改信息
        if (result != null && result.getAlive() == 1) {
            userDao.updateInfo(uid, unickname, urealname, ugender, uphone, umail, uintro, uability);
        }
        ModifyUserInfoRequest modifyUserInfoRequest = userDao.findByUserid(uid);
        return modifyUserInfoRequest;
    }

    /**
     * 发送验证码到学号绑定的邮箱
     *
     * @param uid
     * @param request
     * @return
     */
    @Override
    public List<String> getCodeByID(Long uid, HttpServletRequest request) throws ParameterException {
        if (uid <= 0l || uid == null) {
            throw new ParameterException("uid为空或值非法");
        }
        if (request == null) {
            throw new ParameterException("request为空");
        }
        // 先根据学号查找到邮箱
        User user = userDao.selectById(uid);
        String email = user.getUMail();
        List<String> list = new ArrayList<>();
        //若当前账号已注销
        if (user.getUAlive() == 0) {
            list.add("当前账号已注销，发送验证码失败");
            list.add("false");
            list.add(uid + "");
        }
//        若未绑定邮箱，发送验证码失败
        else if (email == null || email.equals("")) {
            list.add("请先为该学号绑定一个邮箱");
            list.add("false");
            list.add(uid + "");
        }
//        向查询到的邮箱发送验证码
        else {
            HttpSession httpSession = request.getSession();
            Object[] obj = mailService.sendMail(email, httpSession);
            list.add("验证码已发送到学号绑定的邮箱，请注意查收");
            list.add("true");
            for (Object i : obj)
                list.add(i + "");
        }
        return list;
    }

    /**
     * 忘记密码时修改密码
     *
     * @param code
     * @param email
     * @param newPwd
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public String modifyPwBeforeLogin(String code, String email, String newPwd, HttpServletRequest request) throws Exception {
        if (code.length() != 6) {
            throw new ParameterException("code值非法");
        }
        if (email == null || email.equals("")) {
            throw new ParameterException("email为空");
        }
        if (!email.contains("@") || !email.contains(".")) {
            throw new ParameterException("email值非法");
        }
        if (newPwd == null || newPwd.length() > 15) {
            throw new ParameterException("email值非法");
        }
        if (request == null) {
            throw new ParameterException("request为null");
        }
        //检查是否有该邮箱的未注销账号
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUAlive, 1).eq(User::getUMail, email);
        if (userDao.selectCount(wrapper) != 1l) {
            return "不存在此邮箱的活跃账号";
        }

        // 验证验证码是否一致
        boolean isCodeValid = this.isMateCode(code, email, request);
        if (isCodeValid) {
            String enPwd = MD5Utils.inputPassToFormPass(newPwd);
            UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
            updateWrapper.set("u_pwd", enPwd).eq("u_mail", email);
            int modify = userDao.update(null, updateWrapper);
            return modify > 0 ? "密码修改成功" : "无该邮箱绑定的账号";
        }
        return "验证码错误";
    }

    /**
     * 在个人信息界面修改密码
     *
     * @param uid、originalPw、newPw、code、request
     * @return 由验证结果组成的List<Boolean>
     * list(0)存储原密码与数据库密码匹配结果
     * list(1)存储验证码检测结果
     * list(2)存储数据库修改密码操作结果
     */
    @Override
    public List<Boolean> modifyPwByOriginalPw(Long uid, String originalPw, String newPw, String code, HttpServletRequest request) throws Exception {
        if (uid == null || uid == 0l || originalPw == null || originalPw.length() == 0 || newPw == null || newPw.length() == 0 || code.isEmpty()) {
            throw new ParameterException("uid或originalPw或newPw或code为空");
        }
        if (request == null) {
            throw new ParameterException("request为空");
        }
        if (code.length() != 6) {
            throw new ParameterException("code值非法");
        }
        if (newPw == null || newPw.length() > 15 || newPw.length() < 6 || newPw.equals("")) {
            throw new ParameterException("newPw值非法");
        }
        //检查该账户是否仍存在
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUAlive, 1).eq(User::getUId, uid);
        if (userDao.selectCount(wrapper) != 1l) {
            return null;
        }
        //检测原密码与数据库存储的密码是否匹配
        boolean isMateOriginalpw = this.isMateOriginalPw(uid, originalPw);
        List<Boolean> list = new ArrayList<>();
//        第一个元素存储原密码匹配与否
        list.add(isMateOriginalpw);
        if (!isMateOriginalpw) {
            return list;
        }
        // 检查验证码是否一致
        boolean isCodeValid = this.isMateCode(code, userDao.selectById(uid).getUMail(), request);
//        第二个元素存储验证码检验是否通过
        list.add(isCodeValid);
        if (!isCodeValid) {
            return list;
        }
        String enPwd = MD5Utils.inputPassToFormPass(newPw);
//        将新密码存入库
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("u_pwd", enPwd).eq("u_id", uid);
        int isModify = userDao.update(null, updateWrapper);
//        第三个元素存储是否修改密码成功
        list.add(isModify > 0 ? true : false);
        return list;
    }

    /**
     * 注销账号
     *
     * @param code
     * @param email
     * @param pwd
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public String cancelAccount(String code, String email, String pwd, HttpServletRequest request) throws Exception {
        if (code.length() != 6) {
            throw new ParameterException("code值非法");
        }
        if (email == null || email.equals("")) {
            throw new ParameterException("email为空");
        }
        if (!email.contains("@") || !email.contains(".")) {
            throw new ParameterException("email值非法");
        }
        if (pwd == null || pwd.length() > 15 || pwd.length() < 6) {
            throw new ParameterException("pwd值非法");
        }
        if (request == null) {
            throw new ParameterException("request为null");
        }
        //检查该账户是否仍存在
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUAlive, 1).eq(User::getUMail, email);
        if (userDao.selectCount(wrapper) != 1l) {
            return "不存在此邮箱的活跃账号";
        }
        // 验证验证码是否一致
        boolean isCodeValid = this.isMateCode(code, email, request);
        if (isCodeValid) {
//                注销账号
            UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
            updateWrapper.set("u_alive", 0).eq("u_mail", email).eq("u_pwd", pwd);
            int modify = userDao.update(null, updateWrapper);
            return modify > 0 ? "账号注销成功" : "请检查邮箱、密码是否填写正确";
        }
        return "验证码输入错误";
    }

    /**
     * 根据id获取姓名
     *
     * @param id
     * @return
     */
    @Override
    public String getUsenameById(long id) {
        //查询数据库中是否存在该id对应的学号
        String name =
                userDao.selectRealNameByUid(id);
        if (name == null) {
            System.out.println("数据库中不存在学号/工号为" + id + "的人");
            return null;
        }
        return name;
    }


    /**
     * 验证参数的原密码与数据库密码是否匹配
     * 形参：uid（用户学号）、originalPw（传入的原密码）
     * 返回：匹配结果
     */
    @Override
    public Boolean isMateOriginalPw(Long uid, String originalPw) throws ParameterException {
        if (uid == null || uid == 0l || originalPw == null || originalPw.equals("")) {
            throw new ParameterException("uid或originalPw为空");
        }
        if (String.valueOf(uid).length() != 12) {
            throw new ParameterException("uid值非法");
        }
        String pw = userDao.selectById(uid).getUPwd();
        String enOriginalPw = MD5Utils.inputPassToFormPass(originalPw);
        boolean isMateOriginalpw = pw.equals(enOriginalPw);
        return isMateOriginalpw;
    }

    /**
     * 验证码是否匹配
     *
     * @param code
     * @param email
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public Boolean isMateCode(String code, String email, HttpServletRequest request) throws Exception {
        if (code.length() != 6) {
            throw new ParameterException("code值非法");
        }
        if (email == null || email.equals("")) {
            throw new ParameterException("email为空");
        }
        if (!email.contains("@")) {
            throw new ParameterException("email值非法");
        }
        if (request == null) {
            throw new ParameterException("request为null");
        }
        HttpSession session = request.getSession();
        UserDTO userDTO = new UserDTO();
        userDTO.setCode(code);
        userDTO.setEmail(email);
        // 验证验证码是否一致
        return mailService.validateCode(userDTO, session);
    }

    /**
     * 检测用户必要信息是否完善
     *
     * @param user
     * @return
     * @throws Exception
     */
    @Override
    public Boolean isPerfectInfo(User user) throws Exception {
        if (user != null) {
            //检测昵称、性别、手机、邮箱是否填写
            if (stringUtils.isEmpty(user.getUNickname()) ||
                    stringUtils.isEmpty(user.getUGender()) ||
                    stringUtils.isEmpty(user.getUPhone()) ||
                    stringUtils.isEmpty(user.getUMail())) {
                return false;
            }
            return true;
        }
        return null;
    }


}